#include "Orion20m.h"
#include "cvel.h"

void ORION::UpdateHUDdata(int mode) {
	static bool first=true;
	if(first) {
		first=false;
		cfg->caminternal=oapiCameraInternal();
	}
	hdata->vehmasst=GetMass();
	hdata->vehmassf=GetFuelMass();
//	rembombs=vehmassf/500;
	GetThrustVector(hdata->vehthrustv);
	GetTorqueVector(hdata->vehtorquev);
	GetWeightVector(hdata->vehweightv);
	GetSuperstructureCG(hdata->vehsscg);


	hdata->fuelratiomain=0.0;
	hdata->maxfuelmain=GetPropellantMaxMass(ph_main);
	hdata->currfuelmain=GetPropellantMass(ph_main);
	if(hdata->maxfuelmain>0.0) hdata->fuelratiomain=hdata->currfuelmain/hdata->maxfuelmain;
#ifdef TESTING
	GetThrusterDir(th_orion[0], hdata->thdirmain);
#endif
	hdata->fuelratiorcs=0.0;
	hdata->maxfuelrcs=GetPropellantMaxMass(ph_RCS);
	hdata->currfuelrcs=GetPropellantMass(ph_RCS);
	if(hdata->maxfuelrcs>0.0) hdata->fuelratiorcs=hdata->currfuelrcs/hdata->maxfuelrcs;

	if(hdata->vehmasst>0.0) {
		SSCOUNT=0;
		ssmass=0.0;
		VESSEL * s = oapiGetVesselInterface(GetHandle());
		getsuperstructuremass(s);
		hdata->ssmass=ssmass-hdata->vehmasst;
	}

	double massnofuel;

	massnofuel=(hdata->vehmasst-hdata->currfuelmain);
	hdata->remDVmain=log(massnofuel/(massnofuel+hdata->currfuelmain))*(cfg->Ispmain)*(-1);
	massnofuel=massnofuel+hdata->ssmass;
	hdata->remDVmainstack=log(massnofuel/(massnofuel+hdata->currfuelmain))*(cfg->Ispmain)*(-1);
	hdata->penaltyDVmain=hdata->remDVmain-hdata->remDVmainstack;

	massnofuel=(hdata->vehmasst-hdata->currfuelrcs);
	hdata->remDVrcs=log(massnofuel/(massnofuel+hdata->currfuelrcs))*(cfg->IspRCS)*(-1);
	massnofuel=massnofuel+hdata->ssmass;
	hdata->remDVrcsstack=log(massnofuel/(massnofuel+hdata->currfuelrcs))*(cfg->IspRCS)*(-1);
	hdata->penaltyDVrcs=hdata->remDVrcs-hdata->remDVrcsstack;
	//
#ifdef TESTING	
	VECTOR3 lspos, rspos;//holder for relative position from sun
    VECTOR3 lppos = {0,0,1};//solar panels tangent always point along z axis
    //VESSEL * v = oapiGetVesselInterface(vesselObject);//identify our vessel
    GetGlobalPos(rspos); //relative sun position
    rspos = -rspos/length(rspos);//invert and normalize sun relative position
    MATRIX3 R;//holder for rotation matrix
    GetRotationMatrix(R);//get rotation matrix
    lspos = tmul(R,rspos);//inverse rotation
    hdata->sunangle = (((acos(dotp(lspos,lppos)))*(180/PI)));
#endif

	for(int i=0;i<NUMDOCKS;i++) {
		docks[i].selected=(i==SelectedUmmuDock?TRUE:FALSE);
		if(DockingStatus(i)) {
			docks[i].docked=GetDockStatus(docks[i].handle);
			oapiGetObjectName(docks[i].docked,docks[i].dockedname,64);
		} else {
			docks[i].docked=NULL;
			sprintf(docks[i].dockedname,"EVA\0");
		}
	}
}

void ORION::hudprint(oapi::Sketchpad *skp, int x, int y, char buf[1024]) {
	if(cfg->hudshadow) {
		#define OFS 1
		DWORD oldcolor=skp->SetTextColor (cfg->hudshadowcolor);
		skp->Text(x-OFS,y-OFS,buf,(int)strlen(buf));// FIXME: shitty
		skp->Text(x-OFS,y+OFS,buf,(int)strlen(buf));
		skp->Text(x+OFS,y-OFS,buf,(int)strlen(buf));
		skp->Text(x+OFS,y+OFS,buf,(int)strlen(buf));
		skp->SetTextColor (oldcolor);
		skp->Text(x,y,buf,(int)strlen(buf));
	} else {
		skp->Text(x,y,buf,(int)strlen(buf));
	}
}


#define hudline(s, ...) {char buf[1024];\
	sprintf_s(buf, 1024, s, __VA_ARGS__);\
		hudprint(skp,_from_side, _from_top, buf);\
		_from_top += 2*_interval;\
}

#define thgrouphud(g,str){int thcount=GetGroupThrusterCount(g);\
	for (int i = 0; i < thcount; i++) {\
		th = GetGroupThruster(g, i);\
		GetThrusterRef(th, thref);\
		GetThrusterDir(th, thdir);\
		GetThrusterMoment(th,thmomentlin,thmomenttor);\
		thlevel=GetThrusterLevel(th);\
		thmax=GetThrusterMax(th);\
		thisp=GetThrusterIsp(th);\
		hudline("%s[%d]: %.1f%% %.2f, torque: (%+.2f,%+.2f,%+.2f)",str,i,thlevel*100,thmax,thmomenttor);\
	}\
}

/*
		if (rcs_shift_mode>=0) {\
			if (rcs_shift_mode==1) SetThrusterRef(th,_V(\
				thref.x+(rcs_shift_vec.x*-1)+vehsscg.x, \
				thref.y+(rcs_shift_vec.y*-1)+vehsscg.y, \
				thref.z+(rcs_shift_vec.z*-1)+vehsscg.z\
				));\
		}\
	}\
}
*/

 



void ORION::drawbox(oapi::Sketchpad *skp, int x, int y, int height, int width, double ratio) {

		char buf[128];
		oapi::Pen *rectfill;
		oapi::Pen *oldpen;
		oapi::Brush *rectfillbrush;
		oapi::Brush *oldbrush;

		rectfill=oapiCreatePen(1,1,cfg->hudfillcolor);//0x555500
		rectfillbrush=oapiCreateBrush(cfg->hudfillcolor);

		oldpen=skp->SetPen(rectfill);
		oldbrush=skp->SetBrush(rectfillbrush);
		int boxx2=x+width;
		int boxy2=y+height;

		skp->Rectangle(x,y,x+(int)(width*ratio),boxy2);
		oapiReleasePen(rectfill);
		oapiReleaseBrush(rectfillbrush);
		skp->SetPen(oldpen);
		skp->SetBrush(oldbrush);
		skp->Rectangle(x-1,y-1,boxx2+1,boxy2+1);

		#define bOFS 1
		DWORD oldtextcolor=skp->SetTextColor (cfg->hudshadowcolor);
		x=x+(width/2);
		y=y-1;
		sprintf_s(buf,"%.1f%%",ratio*100);
		skp->SetTextAlign(oapi::Sketchpad::CENTER);
		skp->Text(x-bOFS,y-bOFS,buf,(int)strlen(buf));// FIXME: shitty
		skp->Text(x-bOFS,y+bOFS,buf,(int)strlen(buf));
		skp->Text(x+bOFS,y-bOFS,buf,(int)strlen(buf));
		skp->Text(x+bOFS,y+bOFS,buf,(int)strlen(buf));
		skp->SetTextColor (cfg->hudselcolor);
		skp->Text(x,y,buf,(int)strlen(buf));
		skp->SetTextAlign(oapi::Sketchpad::LEFT);
		skp->SetTextColor (oldtextcolor);
		return;
}
bool ORION::clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, oapi::Sketchpad *skp) {

#ifdef BUFFERhud
	if(vhudCreated!=1) {
		dprint("got %i x %i",hps->W,hps->H);
		vhud=oapiCreateSurface (hps->W,hps->H);
		vhudCreated=1;
		dprint("vud==NULL? %i",(vhud==NULL?1:0));
		oapiSetSurfaceColourKey(vhud,0x010203);
		vskp=oapiGetSketchpad(vhud);
		dprint("vskp==NULL? %i",(vskp==NULL?1:0));

	}
#endif
	skp->SetFont (hudfont);

	double oldcolor=skp->SetTextColor (cfg->hudfontcolor);

	static int side_offset = (int)floor((hps->W)/120.0)+10;
	static int top_offset = (int)floor((hps->H)/5.0);
	static int draw_width = (int)floor((hps->W)/2.0);//3.3);
	static int draw_height = (int)floor((hps->H)/3.3);
	int lowest=0;

	int _interval = 7;//8;//9;//7;//(int)(top_offset/20);
	int _from_top = 10;
	int _from_side = side_offset;

//	int lowest=0;
	THRUSTER_HANDLE th;
	double thlevel,thmax,thisp;
	VECTOR3 thmomentlin,thmomenttor,thref,thdir;
	char safestr[32];
	char camstr[64];
	sprintf_s(camstr,64," <cam%i: %.1fx -- %s>",cfg->cam,60.0/cameras[cfg->cam].apt,cameras[cfg->cam].name);
	hudline("%s%s",hudtitle," -- [Del/Ins] Camera");

	sprintf(safestr," <safety%s%s%s>",
		(cfg->nukesafety1?" 1":""),
		(cfg->nukesafety2?" 2":""),
		(cfg->nukesafety3?" 3":"")
	);
	hudline("%s%s%s%s",
		(cfg->nukearmed?"<Nukes ARMED>":"<Nukes offline>"),
		(cfg->nukesafety1 + cfg->nukesafety2 + cfg->nukesafety3 > 0 ? safestr : "" ),
		(cfg->rcs_cog_comp>0?" <RCS COG-CMP>":""),
		(cfg->cam>0?camstr:"")

	);

	if(cfg->cam!=0) {
		_from_top=top_offset - _interval;
		hudline("Camera #%i: [Left-Right/Up-Down/End] Pan/Reset, [Pgup/Pgdn] Zoom, [Del/Ins/Home]: Next/Prev/Main",cfg->cam);
		//,cfg->cam,cameras[cfg->cam].name,60.0/cameras[cfg->cam].apt);
	}

	_from_top = top_offset + _interval;
	if(cfg->hudmode) {
		char *menuKeys[5] = {"",
			"[ALT A]rm nukes, [ALT 1-3] safeties, [5-6] yield, [J] RCS COG comp, [L] airlock light, [CTRL L] clear log", 
			"[J] RCS COG comp", 
			"Crew: [1]/[2], Airlock: [3]/[4], [E]va, [M] add crew, [L] airlock light","[1]/[2] test"};
		hudline("%s",menuKeys[cfg->hudmode]);
		skp->Line(side_offset, _from_top, draw_width, _from_top);
	}
	if (cfg->hudmode==HUD_EVA) {
		int crewcount=Crew.GetCrewTotalNumber();
		hudline("UMMU %.4f, %d onboard.",Crew.GetUserUMmuVersion(),crewcount);
		//hudline("airlock: %s",(Crew.GetAirlockDoorState()?"open":"closed"));
		int mmuP=SelectedUmmuMember-1;
		if(mmuP<0) mmuP=crewcount-1;
		int mmuN=SelectedUmmuMember+1;
		if(mmuN>crewcount-1) mmuN=0;
		for (int i = 0; i < crewcount; i++) {
			if(SelectedUmmuMember==i) skp->SetTextColor (cfg->hudselcolor);
			hudline("%s %s - %s - %d",
				( SelectedUmmuMember==i ? "-->" :
					( mmuN==i ? "[2]" :
						( mmuP==i ? "[1]" : "   " )
					)
				),
				Crew.GetCrewNameBySlotNumber(i),
				Crew.GetCrewMiscIdBySlotNumber(i),
				Crew.GetCrewAgeBySlotNumber(i)
			);
			if(SelectedUmmuMember==i) skp->SetTextColor (cfg->hudfontcolor);
		}
		lowest=_from_top;
	} else if(cfg->hudmode==HUD_RCS) {
		hudline("COG%s: (L/R, U/D, F/B): %+.4f, %+.4f, %+.4f",(cfg->rcs_cog_comp?"(CMP)":""),hdata->vehsscg);
		hudline("Vehicle mass: %.4f kg, Superstructure mass: %.4f kg",hdata->vehmasst,hdata->ssmass);
//		hudline("ATT level: %f",GetThrusterGroupLevel(ENGINE_ATTITUDE));
		thgrouphud(THGROUP_ATT_PITCHUP,"pitch-U");
		thgrouphud(THGROUP_ATT_PITCHDOWN,"pitch-D");
		thgrouphud(THGROUP_ATT_YAWLEFT,"yaw-L");
		thgrouphud(THGROUP_ATT_YAWRIGHT,"yaw-R");
		thgrouphud(THGROUP_ATT_BANKLEFT,"bank-L");
		thgrouphud(THGROUP_ATT_BANKRIGHT,"bank-R");
		//hudline("rot comp: %s %f, rcs shift = %.4f,%.4f,%.4f",(rot_comp_mode==1?"ON":"OFF"),rot_comp_level,rcs_shift_vec);
		//hudline("sc_proc: %f",sc_proc);
		skp->Line(side_offset, _from_top, draw_width, _from_top);
		skp->SetTextColor(cfg->hudmesgcolor);
		int lp=(syslogp-1)%SYSLOGSIZE;
		if (lp<0) lp=SYSLOGSIZE-1;
		hudline("lastmsg: %s",shiplog[lp].message);
		skp->SetTextColor(cfg->hudfontcolor);

		_from_side = (hps->W) + side_offset - draw_width;
		_from_top=top_offset+(1*_interval);
		if (rcs_shift_mode==1) {
			rcs_shift_mode=2;
			rcs_shift_vec=hdata->vehsscg;
		}
		thgrouphud(THGROUP_ATT_UP,"U");
		thgrouphud(THGROUP_ATT_DOWN,"D");
		thgrouphud(THGROUP_ATT_LEFT,"L");
		thgrouphud(THGROUP_ATT_RIGHT,"R");
		thgrouphud(THGROUP_ATT_FORWARD,"F");
		thgrouphud(THGROUP_ATT_BACK,"B");
	} else if (cfg->hudmode==HUD_MAIN) {
		//#ifdef BOMBFUEL hudline("Mass - total: %0.2fkg, Bombs: %0.2fkg (%.0f bombs)",vehmasst,vehmassf,rembombs); #endif
		char yieldstr[64];
		int old_offset=side_offset;

		drawbox(skp, side_offset, _from_top+4, (_interval*2)-1, 100, hdata->fuelratiomain );
		
		_from_side=side_offset+110;
		_from_top += 2;
		hudline("Bombs: %0.2f kg, DV %.0f m/s",hdata->currfuelmain,hdata->remDVmainstack);
		_from_top -= 2;

		
		sprintf(yieldstr,"Yield: %s",(cfg->nukearmed?"":"(OFFLINE) "));
		int roffs=draw_width-100;
		_from_top -= 2*_interval;
		drawbox(skp, roffs, _from_top+4, (_interval*2)-1, 100, cfg->nukeyield );

		_from_side=roffs-2-skp->GetTextWidth(yieldstr,strlen(yieldstr));
		_from_top += 2;
		hudline(yieldstr);
		_from_top -= 2;

		_from_top += 1*_interval;


		drawbox(skp, side_offset, _from_top+4, (_interval*2)-1, 100, hdata->fuelratiorcs );

		_from_side=side_offset+110;
		_from_top += 2;
		hudline("RCS: %0.2f kg, DV: %.0f m/s",hdata->currfuelrcs,hdata->remDVrcsstack);
		_from_top -= 2;

		_from_top += 1*_interval;
		_from_side=side_offset;

		if(hdata->penaltyDVmain>10.0) {
			hudline("Mass: Ship: %.4f kg + Payload: %.4f kg (-%.0f m/s main DV)",hdata->vehmasst,hdata->ssmass,hdata->penaltyDVmain);
		} else {
			hudline("Mass: Ship: %.4f kg + Payload: %.4f kg",hdata->vehmasst,hdata->ssmass);
		}
		hudline("COG%s: (L/R, U/D, F/B): %+.6f, %+.6f, %+.6f",(cfg->rcs_cog_comp?"(CMP)":""),hdata->vehsscg);
#ifdef TESTING
		hudline("Ejection vector: %.5f, %.5f, %.5f",hdata->thdirmain);
#endif

//		hudline("boom(%d)->%0.4f",boom->IsActive(),boom->GetIntensity());
//		hudline("PMI: %.4f, %.4f, %.4f",vehpmi.x,vehpmi.y,vehpmi.z);
		hudline("Thrust: %+.2f, %+.2f, %+.2f  Torque: %+.2f, %+.2f, %+.2f",
			hdata->vehthrustv,
			hdata->vehtorquev	
		);
		//hudline("Weight: %.2f, %.2f, %.2f",vehweightv);
#ifdef DEBUGHUD
		hudline(" %d+10,%d,... // W=%d, H=%d, CX=%d, CY=%d, Scale=%.3f, Markersize=%d",
			side_offset + 10, _from_top,
			hps->W,hps->H,hps->CX,hps->CY,hps->Scale,hps->Markersize
		);
		hudline("side_offset=%d, top_offset=%d, draw_width=%d, draw_height=%d, _interval=%d, _from_top=%d",
			side_offset, top_offset, draw_width, draw_height, _interval, _from_top);
#endif
		skp->Line(side_offset, _from_top+1, draw_width, _from_top+1);
	
		skp->SetTextColor(cfg->hudmesgcolor);
		for(int i=syslogp;i<SYSLOGSIZE+syslogp;i++) {
			if(strlen(shiplog[i%SYSLOGSIZE].message)) {
				hudline("syslog %s",shiplog[i%SYSLOGSIZE].message);
			}
		}
		skp->SetTextColor(cfg->hudfontcolor);
	} else if (cfg->hudmode==HUD_CAMERA) {
		if(cfg->cam > 0) {
			hudline("testcamx: _mode: %f, yaw_proc: %f pitch_proc: %f",cfg->camyawmode,cameras[cfg->cam].yaw_proc,cameras[cfg->cam].pitch_proc);
			hudline("dir: %f, %f, %f",cameras[cfg->cam].dir);
			hudline("test %f, %f, %f",
				yawpitch2cart(
					cameras[cfg->cam].yaw_proc*PI*2,
					cameras[cfg->cam].pitch_proc*PI*2
				)
			);
		}

		skp->SetTextColor(cfg->hudmesgcolor);
		for(int i=syslogp;i<SYSLOGSIZE+syslogp;i++) {
			if(strlen(shiplog[i%SYSLOGSIZE].message)) {
				hudline("syslog %s",shiplog[i%SYSLOGSIZE].message);
			}
		}
		skp->SetTextColor(cfg->hudfontcolor);
		
	}
////////////////////
//	side_offset = (hps->W) - side_offset - draw_width;
		_from_side=(hps->W) + side_offset - draw_width;
		_from_top=top_offset+10+(2*_interval);
		
	if (cfg->hudmode==HUD_EVA) {
		_from_top += 1*_interval;
		
		_from_side=_from_side - 100;

		
		int dc=NUMDOCKS;//DockCount();

		int dockP=SelectedUmmuDock-1;
		if(dockP<0) dockP=dc-1;
		int dockN=SelectedUmmuDock+1;
		if(dockN>dc-1) dockN=0;

		for (int i = 0; i < dc; i++) {
			if(SelectedUmmuDock==i) skp->SetTextColor (cfg->hudselcolor);
			hudline("%s %d -> %s", 
				(SelectedUmmuDock==i ? "-->" : 
					(dockN==i ? "[4]" : 
						(dockP==i ? "[3]" : "   " )
					)
				),
				i+1,
				docks[i].dockedname
			);
			if(SelectedUmmuDock==i) skp->SetTextColor (cfg->hudfontcolor);
		}

		_from_side = side_offset;//(int)floor((hps->W)/120.0);
		if(_from_top<lowest) _from_top=lowest;
		skp->Line(side_offset, _from_top, draw_width, _from_top);
		skp->SetTextColor(cfg->hudmesgcolor);
		int lp=(syslogp-1)%SYSLOGSIZE;
		if (lp<0) lp=SYSLOGSIZE-1;
		hudline("lastmsg: %s",shiplog[lp].message);
		skp->SetTextColor(cfg->hudfontcolor);
	} else if(cfg->hudmode==HUD_RCS) {
	} else if(cfg->hudmode==HUD_MAIN) {
#ifdef TESTING
		hudline("Sun: %f",hdata->sunangle);

#endif		
	}
	if(cfg->cam > 0) {

	}
#ifdef BUFFERhud
	if(vhudCreated==1) {
		//oapiColourFill (vhud,0x010203,0,0,200,200);
		oapi::Pen * wut=oapiCreatePen(1,3,0xFEFEFE);
		vskp->SetPen(wut);
		vskp->Line(10,10,500,500);
		oapiReleasePen(wut);
		SURFHANDLE wtf=skp->GetSurface();
        dprint("hudsurface==NULL? %i",(wtf==NULL?1:0));
		oapiBlt(vhud,wtf,1,1,1,1,hps->W-20,hps->H-20);
	}
#endif
	return true;
}
